//////////////////////////////////////////////
// Buffer.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward declarations ---------------------

namespace nkGraphics
{
	class System ;

	struct BufferCpuDataDescriptor ;
	struct MapRequestDescriptor ;
	struct ResourceCpuDataDescriptor ;
	struct ResourceGpuCopyDescriptor ;
	struct UnmapRequestDescriptor ;
}

namespace nkMemory
{
	class Buffer ;
}

/// Includes ---------------------------------
	
// nkGraphics
#include "MapResult.h"

#include "../Buffers/Enums/BufferBindFlag.h"
#include "../Buffers/Enums/BufferCpuAccessFlag.h"
#include "../Buffers/Enums/BufferUsage.h"

#include "../Dll/DllDefines.h"

#include "../Resources/Enums/ResourceMiscFlag.h"

#include "../Resources/ShaderResource.h"

#include "../Utils/DxDefinesWrapper.h"

// nkExport
#include <NilkinsExport/Exportable/Exportable.h>

// nkMemory
#include <NilkinsMemory/Containers/BufferView.h>

#include <NilkinsMemory/Pointers/UniquePtr.h>

/// Class ------------------------------------

namespace nkGraphics
{
	class DLL_GRAPHICS_EXPORT Buffer : public ShaderResource, public nkExport::Exportable
	{			
		public :
		
			// Destructor
			virtual ~Buffer () ;

			// Getters
			unsigned int getElementByteSize () const ;
			unsigned int getElementCount () const ;
			unsigned int getTotalByteSize () const ;
			// Plus abstrait
			virtual BUFFER_USAGE getUsage () const = 0 ;
			virtual BUFFER_BIND_FLAG getBindFlag () const = 0 ;
			virtual BUFFER_CPU_ACCESS_FLAG getCpuAccessFlag () const = 0 ;
			virtual RESOURCE_MISC_FLAG getMiscFlag () const = 0 ;

			// Setters
			void setCpuData (nkMemory::BufferView<> data) ;
			void setCpuDataCopy (nkMemory::BufferView<> data) ;
			void setCpuDataForward (nkMemory::Buffer&& data) ;
			virtual void freeCpuData () ;
			virtual void setElementByteSize (unsigned int value) ;
			virtual void setElementCount (unsigned int value) ;
			virtual void copyParams (const Buffer& other) ;
			// Plus abstraits
			virtual void setUsage (BUFFER_USAGE value) = 0 ;
			virtual void setBindFlag (BUFFER_BIND_FLAG value) = 0 ;
			virtual void setCpuAccessFlag (BUFFER_CPU_ACCESS_FLAG value) = 0 ;
			virtual void setMiscFlag (RESOURCE_MISC_FLAG value) = 0 ;

			// Map (Renderer)
			virtual MapResult map (const MapRequestDescriptor& requestDesc) = 0 ;
			virtual void unmap (const UnmapRequestDescriptor& requestDesc) = 0 ;
			virtual void gpuCopyFrom (Buffer& other, const ResourceGpuCopyDescriptor& descriptor) = 0 ;

			// Utilisation buffer en shader resource
			virtual void prepareForShaderResourceUsage (bool value = true) ;
			virtual void prepareForComputeResourceUsage (bool value = true) ;
			virtual void prepareForOutputStreamUsage (bool value = true) ;

			// Import export
			virtual void exportClassToTree (nkExport::Node* rootNode) override ;
			virtual void importClassFromTree (nkExport::Node* rootNode) override ;

			// Operators
			Buffer& operator= (const Buffer&) = delete ;

		public :

			// Statics
			static nkMemory::UniquePtr<Buffer> create (System* system = nullptr) ;

		protected :

			// Functions
			// Constructors
			Buffer (System* system) noexcept ;
			Buffer (const Buffer&) = delete ;

			// Cpu data
			nkMemory::BufferView<> _getCpuData () const ;
			bool _getCpuDataIsView () const ;
			nkMemory::Buffer _getCpuDataTransfer () ;

		protected :
		
			// Attributs
			// Potential cpu Data
			nkMemory::UniquePtr<BufferCpuDataDescriptor> _cpuData ;

			// Info for size
			unsigned int _elementByteSize ;
			unsigned int _elementCount ;

			// Current flags
			bool _computeUseActivated ;
			bool _shaderUseActivated ;
			bool _outputStreamUse ;
	} ;
}